/**
 * Created by Administrator on 2017/1/6.
 */

var UserToken = module.exports;
var common = require('../util/common.js');
var redis_db = require('./redis_db.js');
var CONFIG = require('../config.js');

function createTokenInfo(userInfo) {
    var ret = {
        uid: userInfo.uid,
        openid: userInfo.openid,
        tokenS: 'TKN:' + common.randomString(1) + ':' + common.randomString(1) + ':' + common.randomString(1) + ':' + common.randomString(13),
        isAdmin: userInfo.isAdmin ? 1 : 0,
    };
    if (userInfo.app_sid) {
        ret.app_sid = userInfo.app_sid;
        ret.tokenS += ':' + userInfo.app_sid;
    }
    return ret;
}

function makeKeyAcc2Token(isAdmin, openid, app_sid, mainUid) {
    var keyAcc2Token = isAdmin ? 'a2tA:' : 'a2tU:';
    if (openid.length > 7) {
        keyAcc2Token += openid.substr(0, 3) + ':' +
            openid.substr(3, 2) + ':' +
            openid.substr(5, 2) + ':' +
            openid.substr(7);
    } else {
        keyAcc2Token += openid;
    }
    if (app_sid) {
        keyAcc2Token += ':' + app_sid;
        if (mainUid) {
            keyAcc2Token += ':' + mainUid;
        }
    }
    return keyAcc2Token;
}

function decodeTokenInfo(token) {
    var ret = {
        tokenS: token
    }; 
    return ret;
}

function onLoginSaveInfo(acc2tokenKey, tkInfo, logIdx, cb) {
    var expireTime = tkInfo.isAdmin ? 60 * 60 * 24 * 7 : 48 * 3600;
    tkInfo.renewTime = new Date().getTime();
    redis_db.set(tkInfo.tokenS, JSON.stringify(tkInfo), expireTime, function (err) {
        if (err) {
            console.log(err);
            return;
        }
    });
    redis_db.set(acc2tokenKey, tkInfo.tokenS, expireTime, function (err) {
        if (err) {
            console.log(err);
            return;
        }
    });
    var token = tkInfo.tokenS;
    if (logIdx) {
        token += '_' + logIdx;
    }
    if (cb) cb(null, token);
}

function onLoginStep1_TokenInfo(acc2tokenKey, tkInfo, userInfo, cb) {
    if (!tkInfo) {
        tkInfo = createTokenInfo(userInfo);
    }

    if (userInfo.isAdmin) {
        tkInfo.purview_Id = userInfo.purview_Id;
        tkInfo.role = userInfo.role;
    } else if (userInfo.app_sid) {
        var logLvl = 0;

        if (userInfo.main_userInfo) {
            if (userInfo.vipInfo) tkInfo.vipInfo = userInfo.vipInfo;
            else tkInfo.vipInfo = [];

            if (userInfo.multiLogin > 0) {
                if (!tkInfo.vipInfo.some(function (t) {
                        if (t.vip_sid == 'multiLogin' && !isNaN(t.lvl)) {
                            logLvl = parseInt(t.lvl) + 1;
                            return true;
                        }
                        return false;
                    })) {
                    logLvl = 1;
                }
            }

            tkInfo.main_userInfo = userInfo.main_userInfo;
            if (userInfo.group_name) tkInfo.group_name = userInfo.group_name;
            if (userInfo.app_sid) tkInfo.app_sid = userInfo.app_sid;
            if (userInfo.sub_status) tkInfo.sub_status = userInfo.sub_status;
            if (userInfo.name) tkInfo.name = userInfo.name;
            if (userInfo.sub_auth) tkInfo.sub_auth = userInfo.sub_auth;
            if (userInfo.sub_name) tkInfo.sub_name = userInfo.sub_name;
        } else if (userInfo.appInfo && userInfo.appInfo.length > 0) {
            tkInfo.appInfo = userInfo.appInfo;
            
            if (userInfo.multiLogin > 0) {
                if (tkInfo.appInfo[0].vipInfo && tkInfo.appInfo[0].vipInfo.multiLogin && tkInfo.appInfo[0].vipInfo.multiLogin.vip_level) logLvl = tkInfo.appInfo[0].vipInfo.multiLogin.vip_level + 1;
                if (!logLvl) logLvl = 1;
            }
        }
        if (logLvl > 0) {
            tkInfo.logIdx = tkInfo.logIdx ? tkInfo.logIdx : 0;
            if (++tkInfo.logIdx > 9999) tkInfo.logIdx = 1;
            tkInfo.logLvl = logLvl;
        }
    }
    onLoginSaveInfo(acc2tokenKey, tkInfo, tkInfo.logIdx, cb);
}
UserToken.onLogin = function (userInfo, cb) {
    var mainUid = userInfo.main_userInfo ? userInfo.main_userInfo.uid : 0;
    var acc2tokenKey = makeKeyAcc2Token(userInfo.isAdmin, userInfo.openid, userInfo.app_sid, mainUid);

    redis_db.get(acc2tokenKey, function (err, tokenS) {
        if (err) {
            cb(err);
            return;
        }
        if (!tokenS) {
            onLoginStep1_TokenInfo(acc2tokenKey, null, userInfo, cb);
            return;
        }

        redis_db.get(tokenS, function (err1, result) {
            if (err1) {
                cb(err1);
                return;
            }
            if (!result) {
                redis_db.del(tokenS, doNothing);
                onLoginStep1_TokenInfo(acc2tokenKey, null, userInfo, cb);
                return;
            }

            var tkInfo = JSON.parse(result);
            onLoginStep1_TokenInfo(acc2tokenKey, tkInfo, userInfo, cb);
            return;
        });
    });
};

UserToken.checkLogin = function (tokenCpx, cb) {
    if (!tokenCpx) {
        cb(null, false);
    } else {
        var tokenInput = decodeTokenInfo(tokenCpx); //返回token
        redis_db.get(tokenInput.tokenS, function (err, result) {
            if (err) {
                cb(err);
                return;
            } else {
                if (result) {
                    var tkInfo = JSON.parse(result);
                    if (!tkInfo) {
                        cb('尚未登陆本应用!');
                        return;
                    }
                    if (!tkInfo.isAdmin) {
                        if (tokenInput.logIdx > 0 && tkInfo.logIdx) {
                            var logIdx = tokenInput.logIdx;
                            var logLvl = tkInfo.logLvl ? tkInfo.logLvl : 1;
                            if ((logIdx > tkInfo.logIdx && logIdx <= tkInfo.logIdx + 9999 - logLvl) ||
                                (logIdx < tkInfo.logIdx && logIdx <= tkInfo.logIdx - logLvl)) {
                                cb('已在其他终端登陆, 此终端已离线, 请重新登陆!');
                                return;
                            }
                        }
                    }
                    if (tkInfo.renewTime + 90000 < new Date().getTime()) {
                        var expireTime = tkInfo.isAdmin ? 1800 : 48 * 3600;
                        var mainUid = tkInfo.main_userInfo ? tkInfo.main_userInfo.uid : 0;
                        var acc2tokenKey = makeKeyAcc2Token(tkInfo.isAdmin, tkInfo.openid, tkInfo.app_sid, mainUid);
                        redis_db.expire(acc2tokenKey, expireTime, doNothing);
                        redis_db.expire(tkInfo.tokenS, expireTime, doNothing);
                    }
                    cb(null, tkInfo);
                    return;
                }else{
                    cb('checkLogin中的请先登录');
                }
            }
        });
    }
};

UserToken.checkOtherLogin = function (tokenCpx, cb) {
    if (!tokenCpx) {
        cb(null, false);
    } else {
        var tokenInput = {
            tokenS: tokenCpx
        };
        redis_db.get(tokenInput.tokenS, function (err, result) {
            if (err) {
                cb(err);
                return;
            }
            if (result) {
                var tkInfo = JSON.parse(result);
                if (!tkInfo.isAdmin) {
                    if (tokenInput.logIdx > 0 && tkInfo.logIdx) {
                        var logIdx = tokenInput.logIdx;
                        var logLvl = tkInfo.logLvl ? tkInfo.logLvl : 1;
                        if ((logIdx > tkInfo.logIdx && logIdx <= tkInfo.logIdx + 9999 - logLvl) ||
                            (logIdx < tkInfo.logIdx && logIdx <= tkInfo.logIdx - logLvl)) {
                            cb('已在其他终端登陆, 此终端已离线, 请重新登陆!');
                            return;
                        }
                    }
                }
                if (tkInfo.renewTime + 90000 < new Date().getTime()) {
                    var expireTime = tkInfo.isAdmin ? 1800 : 48 * 3600;
                    var mainUid = tkInfo.main_userInfo ? tkInfo.main_userInfo.uid : 0;
                    var acc2tokenKey = makeKeyAcc2Token(tkInfo.isAdmin, tkInfo.openid, tkInfo.app_sid, mainUid);
                    redis_db.expire(acc2tokenKey, expireTime, doNothing);
                    redis_db.expire(tkInfo.tokenS, expireTime, doNothing);
                }
                cb(null, tkInfo);
                return;
            }
            cb('请先登录');
        });
    }
};

//检查系统、产品管理员登录
UserToken.checkAdminLogin = function (token, appSidOrVipSid, cb) {
    var appSid = null;
    var vipSid = null;
    if (CONFIG && CONFIG.appSid && (CONFIG.appSid != 'common' && CONFIG.appSid != appSidOrVipSid)) {
        appSid = CONFIG.appSid;
        vipSid = appSidOrVipSid;
    } else {
        appSid = appSidOrVipSid;
        vipSid = null;
    }
    UserToken.checkAdminAllLogin(token, appSid, vipSid, cb);
    return;
};

//检查多功能的产品管理员登录
UserToken.checkAdminsLogin = function (token, app_sid, roles, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, adminInfo) {
        if (err) {
            cb(err, 403);
            return;
        }
        if (!adminInfo) {
            cb('请先登录', 403);
            return;
        }
        if (!adminInfo.isAdmin) {
            cb('您不是管理员！', 403);
            return;
        }
        if (adminInfo.role.indexOf('admin') >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && adminInfo.role.indexOf('adm_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        for (var i = 0; i < roles.length; i++) {
            var role = roles[i];
            if (adminInfo.role.indexOf(role + '_' + app_sid) >= 0) {
                cb(null, 0, adminInfo);
                return;
            }
        }
        cb('无权限', 400);
        return;
    });
};

//检查系统、产品、功能管理员登录
UserToken.checkAdminAllLogin = function (token, app_sid, vip_sid, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, adminInfo) {
        if (err) {
            cb(err, 403);
            return;
        }

        if (!adminInfo) {
            cb('请先登录', 403);
            return;
        }

        if (!adminInfo.isAdmin) {
            cb('您不是管理员！', 403);
            return;
        }

        if (adminInfo.role.indexOf('admin') >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && adminInfo.role.indexOf('adm_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        if (app_sid && vip_sid && adminInfo.role.indexOf(vip_sid + '_' + app_sid) >= 0) {
            cb(null, 0, adminInfo);
            return;
        }
        cb('无权限', 400);
        return;
    });
};

//检查用户登录、token且返回错误的
// cb(err,errCode,UserInfo)
UserToken.checkUserLogin = function (token, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, userInfo) {
        if (err) {
            console.log(err);
            cb(err, 403);
            return;
        }
        if (!userInfo || (userInfo.isAdmin && userInfo.isAdmin == '1')) {
            cb('checkUserLogin中的请先登录', 403);
            return;
        }
        cb(null, 0, userInfo);
    });
};

//检查用户或管理员登录、token且返回错误的
// cb(err,errCode,UserInfo)
UserToken.checkAllLogin = function (token, identify, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, userInfo) {
        if (err) {
            cb(err, 400);
            return;
        }
        if (!userInfo) {
            cb('请先登录', 403);
            return;
        }
        if (userInfo.isAdmin) {
            if (userInfo.role.indexOf('admin') < 0 && userInfo.role.indexOf('adm_' + CONFIG.appSid) < 0 && userInfo.role.indexOf(identify + '_' + CONFIG.appSid) < 0) {
                cb('无权限', 400);
                return;
            }
        }
        cb(null, 0, userInfo);
    });
};

UserToken.checkMulLogin = function (token, identifys, cb) {
    if (!token) {
        cb('token不为空', 400);
        return;
    }
    UserToken.checkLogin(token, function (err, userInfo) {
        if (err) {
            cb(err, 400);
            return;
        }
        if (!userInfo) {
            cb('请先登录', 403);
            return;
        }
        if (userInfo.isAdmin) {
            if (userInfo.role.indexOf('admin') >= 0 || userInfo.role.indexOf('adm_' + CONFIG.appSid) >= 0) {
                cb(null, 0, userInfo);
                return;
            }
            for (var i = 0; i < identifys.length; i++) {
                var identify = identifys[i];
                if (userInfo.role.indexOf(identify + '_' + CONFIG.appSid) >= 0) {
                    cb(null, 0, userInfo);
                    return;
                }
            }
            return cb('无权限', 400);
        } else {
            cb(null, 0, userInfo);
        }
    });
};

//修改密码后生成新的token
UserToken.updateToToken = function (userInfo, cb) {
    var acc2tokenKey = makeKeyAcc2Token(userInfo.isAdmin, userInfo.openid, userInfo.app_sid, null);
    redis_db.keys(acc2tokenKey + '*', function (err, tokens) {
        if (!err && tokens) {
            tokens.forEach(function (token) {
                redis_db.get(token, function (err, rsp) {
                    if (!err) {
                        redis_db.del(rsp, doNothing);
                    }
                });
                redis_db.del(token, doNothing);
            });
        }
        UserToken.onLogin(userInfo, cb);
    });
};

UserToken.onLogout = function (tokenCpx, cb) {
    var tokenInfo = decodeTokenInfo(tokenCpx);
    redis_db.get(tokenInfo.tokenS, function (err, rsp) {
        if (!err) {
            redis_db.del(rsp, doNothing);
        }
    });
    redis_db.del(tokenInfo.tokenS, doNothing);
    cb(null);
};


UserToken.acc2uToken = function (par, cb) {
    var acc2tokenKey = makeKeyAcc2Token(false, par.openid, par.app_key, null);
    redis_db.get(acc2tokenKey, function (err, tokenS) {
        if (err) {
            return;
        }
        cb(null, tokenS);
        return;
    });
}

UserToken.checkCode = function (data, cb) {
    if (!data.code) {
        cb('Miss code');
        return;
    }
    redis_db.get(data.code, function (err, result) {
        if (err) {
            cb(err);
            return;
        }
        if (result) {
            var codeInfo = JSON.parse(result);
            console.log(codeInfo);
            cb(null, codeInfo);
            redis_db.del(data.code, doNothing); //删除code
            return;
        }
        cb('Code Err');
    });
};

UserToken.makeCode = function (data, cb) {
    var myreg = /^(1)[0-9]{10}$/;
    if (!data.openid || data.openid.length != 11 || !myreg.test(data.openid)) {
        cb('openid有误');
        return;
    }
    var key = getCodeKey(data.openid);
    redis_db.set(key, JSON.stringify(data), 180, function (err) {
        if (err) {
            console.log(err);
            return;
        }
        cb(null, {
            code: key
        });
    });
};

function getCodeKey(openid) {
    return 'CODE:' + common.randomString(2) + ':' + openid.substr(0, 1) + common.randomString(2) + ':' + openid.substr(1, 2) +
        common.randomString(2) + ':' + openid.substr(3, 2) + common.randomString(2) + ':' + openid.substr(5, 2) +
        common.randomString(2) + openid.substr(7, 2) + ':' + common.randomString(2) + openid.substr(9, 2) + ':' +
        common.randomString(2) + openid.substr(11, 1);
}